/*
 * User: Sepheus Angelus
 * Date: 01/03/2008
 * Time: 12:43
 * 
 */

using System;
using System.Text.RegularExpressions;

namespace Aphyros_MUD_Server
{

	/// <summary>
	/// LoginHandler class, provides static methods.  Login is the only accessible method
	/// outside of the class.
	/// </summary>
	public class LoginHandle
	{
		//Private fields
		private static string _Command;
		private static Listener _user;
		private static string Password;
		
		/// <summary>
		/// Handles the login event.
		/// </summary>
		/// <param name="Command">Takes a string with the given command string.</param>
		/// <param name="user">Takes a Listener object of a given thread.</param>
		public static void Login(string Command, Listener user)
		{
			//Set local fields.
			_Command = Command;
			_user = user;
			//Deal with entry.
			FirstEnter();
		}
		
		/// <summary>
		/// Upon entry into the Login section, determine the course of action.
		/// </summary>
		private static void FirstEnter()
		{
			//If we have not been here before.
			if(_user.State == States.None)
			{
				//Get our name.
				GetName();
			}
			//Else, if we have been here before - return to creating account, if we were there.
			else if(_user.State == States.SetName)
			{
				//Create account.
				AccountCreation();
			}
			//We were getting our name.
			else if(_user.State == States.GetName)
			{
				//Return there.
				GetName();
			}
			else if(_user.State == States.GetPass)
			{
				GetPassword();
			}
			else if(_user.State == States.ExistPass)
			{
				ExistingUser();
			}
		}
		
		/// <summary>
		/// Gets and sets the username if it is valid.
		/// </summary>
		private static void GetName()
		{
			//Set username.
			_user.Name = _Command.Trim().Replace(" ","_");
			_user.Name = Regex.Replace(_user.Name,"[^0-9-a-z-_]","",RegexOptions.IgnoreCase);
			//Is the username too short?
			if(_user.Name.Length < 3)
			{
				//Display error.
				_user.Writer.Write(ANSI.BrightRed);
				_user.Writer.WriteLine("Username must be three or more characters long!");
				_user.Writer.Write(ANSI.White);
			}
			else if(_user.Name.Length > 20)
			{
				_user.Writer.Write(ANSI.BrightRed);
				_user.Writer.WriteLine("Username must be less than twenty characters long!");
				_user.Writer.Write(ANSI.White);
			}
			//Name is fine, check if it exists.
			else { UserExist(); }
		}
		
		/// <summary>
		/// Contacts the database to see if the username already exists, otherwisely begins creating the account.
		/// </summary>
		private static void UserExist()
		{
			//Return if we exist.
			bool Exists = Database.GetUser(_user.Name);
			//If we do, welcome us back and log us in.
			if(Exists)
			{
				_user.Writer.Write(ANSI.BrightGreen);
				_user.Writer.WriteLine("Welcome back {0}",_user.Name);
				_user.Writer.WriteLine("What is your password?");
				_user.Writer.Write(ANSI.Hidden);
				_user.State = States.ExistPass;
			}
			//If we do not, ask if we want to have the given name as our account name.
			else if(!Exists)
			{
				//Output decision.
				_user.Writer.Write(ANSI.BrightGreen);
				_user.Writer.WriteLine("So your name is {0} eh? (Y/N)",_user.Name);
				_user.Writer.Write(ANSI.White);
				//Move onto creation process.
				AccountCreation();
			}
		}
		
		private static void GetPassword()
		{
			_user.State = States.GetPass;
			Password = _Command.Trim();
			bool Result = Database.AddUser(_user.Name,Encryption.Encrypt(Password));
			if(Result)
			{
				_user.Login = true;
				_user.Writer.Write(ANSI.BrightCyan);
				_user.Writer.WriteLine("Successfully created account {0}",_user.Name);
				Rooms.Describe(_user);
			}
			else
			{
				_user.Login = false;
				_user.Writer.Write(ANSI.BrightRed);
				_user.Writer.WriteLine("Failed to create account.");
				_user.Writer.WriteLine("Possible database fault, contact administrator.");
				_user.Writer.Write(ANSI.White);
			}
		}
		
		private static void ExistingUser()
		{
			_user.State = States.ExistPass;
			Password = _Command.Trim();
			if(Database.GetUser(_user.Name,Encryption.Encrypt(Password)))
			{
				_user.Login = true;
				_user.Writer.Write(ANSI.BrightCyan);
				_user.Writer.WriteLine("Logged in.");
				Database.LoadUser(_user);
				Rooms.Describe(_user);
			}
			else
			{
				_user.Writer.Write(ANSI.BrightRed);
				_user.Writer.WriteLine("Authentication failed for account {0}",_user.Name);
				_user.Writer.Write(ANSI.BrightGreen);
				_user.Writer.WriteLine("Please try again.");
				_user.Writer.Write(ANSI.Hidden);
			}
		}
		
		/// <summary>
		/// Handles whether the name is accepted and creates account with accepted name.
		/// </summary>
		private static void AccountCreation()
		{
			//Save our state to get response.
			_user.State = States.SetName;
			//Response was affirmative.
			if(_Command.Trim().ToLower() == "y")
			{
				//Display success.
				_user.Writer.Write(ANSI.BrightCyan);
				_user.Writer.WriteLine("{0} it is!",_user.Name);
				_user.Writer.Write(ANSI.BrightGreen);
				_user.Writer.WriteLine("What is the password?");
				_user.Writer.Write(ANSI.Hidden);
				//Add into the database.
				_user.State = States.GetPass;
			}
			//Response was negative.
			if(_Command.Trim().ToLower() == "n")
			{
				//Ask for new name.
				_user.Writer.Write(ANSI.BrightGreen);
				_user.Writer.WriteLine("Ah, what is your name then?!");
				_user.Writer.Write(ANSI.White);
				//Save our state at getting the name.
				_user.State = States.GetName;
			}
		}
	}
}
